package service

import (
	"strings"

	"go.uber.org/zap"
	"go-file-perception-model/internal/config"
	"go-file-perception-model/internal/logger"
)

// ChunkPosition 分块位置信息
type ChunkPosition struct {
	StartPos int
	EndPos   int
}

// PositionCalculator 位置计算器
type PositionCalculator struct {
	config      *config.FileIndexConfig
	textEncoder *TextEncoder
}

// NewPositionCalculator 创建位置计算器
func NewPositionCalculator(config *config.FileIndexConfig) *PositionCalculator {
	return &PositionCalculator{
		config:      config,
		textEncoder: NewTextEncoder(),
	}
}

// CalculateChunkPositions 计算分块在原始文本中的位置
func (c *PositionCalculator) CalculateChunkPositions(text string, chunks []string, isSemantic bool) []ChunkPosition {
	positions := make([]ChunkPosition, len(chunks))
	
	if len(chunks) == 0 {
		return positions
	}
	
	if isSemantic {
		return c.calculateSemanticPositions(text, chunks)
	} else {
		return c.calculateFixedSizePositions(text, chunks)
	}
}

// calculateSemanticPositions 计算语义分块位置
func (c *PositionCalculator) calculateSemanticPositions(text string, chunks []string) []ChunkPosition {
	positions := make([]ChunkPosition, len(chunks))
	currentPos := 0
	
	for i, chunk := range chunks {
		// 清理分块内容，移除首尾空白
		cleanChunk := strings.TrimSpace(chunk)
		
		// 确保当前位置不超出文本范围
		if currentPos >= len(text) {
			currentPos = len(text)
		}
		
		// 查找分块内容在文本中的位置
		foundPos := c.findChunkPosition(text[currentPos:], cleanChunk)
		
		if foundPos == -1 {
			// 如果仍然找不到，使用更智能的估算位置
			logger.Warn("Using estimated position for chunk", 
				zap.Int("chunk_index", i), 
				zap.Int("chunk_length", len(chunk)))
			
			// 使用更保守的估算方法
			chunkLength := len(strings.TrimSpace(chunk))
			
			// 确保不会超出文本范围
			endPos := currentPos + chunkLength
			if endPos > len(text) {
				endPos = len(text)
			}
			
			positions[i].StartPos = currentPos
			positions[i].EndPos = endPos
			currentPos = endPos
		} else {
			// 计算绝对位置
			positions[i].StartPos = currentPos + foundPos
			positions[i].EndPos = positions[i].StartPos + len(cleanChunk)
			
			// 确保不超出文本范围
			if positions[i].EndPos > len(text) {
				positions[i].EndPos = len(text)
			}
			
			// 更新当前位置
			currentPos = positions[i].EndPos
		}
		
		// 最终验证：确保位置是有效的
		if positions[i].StartPos < 0 {
			positions[i].StartPos = 0
		}
		if positions[i].EndPos > len(text) {
			positions[i].EndPos = len(text)
		}
		if positions[i].StartPos >= positions[i].EndPos {
			// 如果开始位置大于等于结束位置，调整为最小有效范围
			positions[i].EndPos = positions[i].StartPos + 1
			if positions[i].EndPos > len(text) {
				positions[i].EndPos = len(text)
				positions[i].StartPos = len(text) - 1
				if positions[i].StartPos < 0 {
					positions[i].StartPos = 0
				}
			}
		}
	}
	
	return positions
}

// findChunkPosition 查找分块在文本中的位置，使用多种策略
func (c *PositionCalculator) findChunkPosition(text, chunk string) int {
	if chunk == "" {
		return -1
	}
	
	// 策略1: 直接查找
	if pos := strings.Index(text, chunk); pos != -1 {
		return pos
	}
	
	// 策略2: 查找前50个字符
	if len(chunk) > 50 {
		prefix := strings.TrimSpace(chunk[:50])
		if pos := strings.Index(text, prefix); pos != -1 {
			return pos
		}
	}
	
	// 策略3: 查找前30个字符
	if len(chunk) > 30 {
		prefix := strings.TrimSpace(chunk[:30])
		if pos := strings.Index(text, prefix); pos != -1 {
			return pos
		}
	}
	
	// 策略4: 查找前20个字符
	if len(chunk) > 20 {
		prefix := strings.TrimSpace(chunk[:20])
		if pos := strings.Index(text, prefix); pos != -1 {
			return pos
		}
	}
	
	// 策略5: 分词查找（查找分块中的关键词）
	words := strings.Fields(chunk)
	if len(words) > 0 {
		// 查找第一个词
		if pos := strings.Index(text, words[0]); pos != -1 {
			return pos
		}
		
		// 如果有多个词，查找前几个词的组合
		if len(words) > 1 {
			firstTwoWords := words[0] + " " + words[1]
			if pos := strings.Index(text, firstTwoWords); pos != -1 {
				return pos
			}
		}
	}
	
	return -1
}

// getTotalChunksLength 计算所有分块的总长度
func (c *PositionCalculator) getTotalChunksLength(chunks []string) int {
	total := 0
	for _, chunk := range chunks {
		total += len(strings.TrimSpace(chunk))
	}
	return total
}

// calculateFixedSizePositions 计算固定大小分块位置
func (c *PositionCalculator) calculateFixedSizePositions(text string, chunks []string) []ChunkPosition {
	positions := make([]ChunkPosition, len(chunks))
	chunkSize := c.config.ChunkSize
	overlap := c.config.ChunkOverlap
	step := chunkSize - overlap
	
	currentPos := 0
	for i := range chunks {
		// 计算分块的结束位置
		endPos := currentPos + len(chunks[i])
		
		// 确保不超过文本长度
		if endPos > len(text) {
			endPos = len(text)
		}
		
		positions[i].StartPos = currentPos
		positions[i].EndPos = endPos
		
		// 更新当前位置，考虑重叠
		currentPos += step
		if currentPos >= len(text) {
			break
		}
	}
	
	return positions
}

// findBestMatch 查找最佳匹配位置（保留用于固定大小分块）
func (c *PositionCalculator) findBestMatch(text, chunk string) int {
	// 使用新的查找方法
	return c.findChunkPosition(text, chunk)
}

// CalculateLineNumber 根据字符位置计算行号
func (c *PositionCalculator) CalculateLineNumber(content string, pos int) int {
	// 处理边界情况
	if pos < 0 {
		return 1 // 默认返回第一行
	}
	
	// 如果位置超出内容长度，使用最后一个有效位置
	if pos >= len(content) {
		pos = len(content) - 1
	}
	
	// 确保位置在UTF-8字符边界上
	adjustedPos := c.textEncoder.FindNearestUTF8Boundary(content, pos)
	if adjustedPos != pos {
		pos = adjustedPos
	}
	
	lineNumber := 1
	for i := 0; i <= pos && i < len(content); i++ {
		if content[i] == '\n' {
			lineNumber++
		}
	}
	
	return lineNumber
}